/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019.
 * Description: support hungtask enhance feature
 * Author: chenshiyan <chenshiyan@huawei.com>
 * Create: 2018-08-28
 */

#ifndef RTOS_LINUX_ILOCKDEP_H
#define RTOS_LINUX_ILOCKDEP_H

#include <linux/kernel.h>

#ifdef CONFIG_RTOS_ILOCKDEP
struct task_struct;

struct ilockdep_map {
	void *key;
	const char *name;
	unsigned int cpu;
	unsigned long ip;
};

struct ilockdep {
	void			*locking;
	const char		*locking_name;
	struct ilockdep_map	held_locks[CONFIG_DEBUG_ILOCKDEP_NUM];
	unsigned int		depth;
};

extern bool ilockdep_unlocking_and_unholding_locks(struct task_struct *t);
extern void ilockdep_acquired(struct ilockdep_map *dep, unsigned long ip, void *lock_addr);
extern void ilockdep_release(struct ilockdep_map *dep, unsigned long ip, void *lock_addr);
extern void ilockdep_acquire(struct ilockdep_map *dep, unsigned long ip, void *lock_addr);
extern void ilockdep_init(struct ilockdep *dep);
extern void ilockdep_clear_locking(struct task_struct *p);
extern void show_ilockdep_info(struct task_struct *t);
extern struct kmem_cache *ilockdep_cachep;
extern struct ilockdep ilockdep_init_task;
#ifdef CONFIG_RTOS_KBOX
extern unsigned int sysctl_hung_task_log_size;
extern int proc_hungtask_log_size(struct ctl_table *table, int write,
				void __user *buffer, size_t *lenp, loff_t *ppos);
#endif

extern unsigned int sysctl_hung_task_show_count;
extern int proc_hungtask_show_count(struct ctl_table *table, int write,
				void __user *buffer, size_t *lenp, loff_t *ppos);


#define ILOCKDEP_CONTENDED(_lock, try, lock) \
do { \
	lock(_lock); \
	ilockdep_acquired(&(_lock)->idep_map, _RET_IP_, (void *)_lock); \
} while (0)

#define ILOCKDEP_CONTENDED_RETURN(_lock, try, lock)			\
({								\
	int ____err = 0;					\
	____err = lock(_lock);				\
	if (!____err)						\
		ilockdep_acquired(&(_lock)->idep_map, _RET_IP_, (void *)_lock);	\
	____err;						\
})

#else
# define ilockdep_acquired(l, i, a)	do { } while (0)
# define ilockdep_acquire(l, i, a)	do { } while (0)
# define ilockdep_release(l, i, a)	do { } while (0)
# define ilockdep_init(l)		do { } while (0)
# define ilockdep_clear_locking(p)	do { } while (0)
# define show_ilockdep_info(p)		do { } while (0)
#endif

#endif /* RTOS_LINUX_ILOCKDEP_H */
